/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wiView.graphics.Drawer.NetworkEventDispatcher;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;
import wiBase.baseObject.Event;
import wiView.graphics.Drawer.GraphAnimation.*;
import wiView.graphics.GraphObject.*;
import wiEngine.WiEngine;

/**
 *
 * @author Hoang
 */
public class EventDispatcher implements IEventDispatcher {

    WiEngine engine;
    WiGraph graph;

    public EventDispatcher(WiGraph g, WiEngine e) {
        graph = g;
        engine = e;

    }
    double getBasedSpeed(double startTime, double endTime){
        return 1.2 * 1E6 / (endTime - startTime);
    }
    double getSpeed(double startTime, double endTime) {
        return 1.1 * 1E6 / (endTime - startTime) / engine.getSpeed();
    }


    @Override
    public ArrayList<Animator> CreateAnimator(Event e) {
        return _createAnimators(e);
    }

    public ArrayList<Animator> _createAnimators(Event e) {
        if (e == null) {
            return null;
        }

        ArrayList<Animator> result = new ArrayList<>();
        if(graph.getwiNode(e.sourceId) == null && graph.getwiNode(e.nodeId) == null)
            return result;
        
        switch (e.type) {
            case "sleep":
                NodeAnimator a = new NodeAnimator();
                a.id = e.nodeId + e.getTime();
                a.NodeID = e.nodeId;
                a.type = NodeAnimator.Type.Sleep;
                result.add(a);
                break;
            case "wake":
                a = new NodeAnimator();
                a.id = e.nodeId + e.getTime();
                a.NodeID = e.nodeId;
                a.type = NodeAnimator.Type.Wake;
                result.add(a);
                break;
            case "move":
                break;
            case "drop":
                break;
            case "send":
                if (e.destId.equals("-1")) {
                    // broadcast
                    if (e.lstEventReceive == null || e.lstEventReceive.size() == 0) {
                        return null;
                    } else 
                    {
                        //for node
                        a = new NodeAnimator();
                        a.id = e.nodeId + e.getTime();
                        a.NodeID = e.sourceId;
                        a.type = NodeAnimator.Type.Broadcast;
                        result.add(a);
                        //for edge
                        for (Event event : e.lstEventReceive) {
                            EdgeAnimator ea = new EdgeAnimator();
                            ea.n0 = e.sourceId;
                            ea.n1 = event.destId;
                            ea.packetID = e.packetId;
                            ea.speed = getSpeed(e.getTime(), event.getTimeReceive());
                            ea.id = e.packetId + "-" + event.getTimeReceive();
                            ea.timeStart = -1;
                            ea.type = EdgeAnimator.Type.SEND;

                            result.add(ea);
                        }
                    }
                } else {   // simple send
                    /// for node
                    a = new NodeAnimator();
                    a.id = e.nodeId + e.getTime();
                    a.NodeID = e.sourceId;
                    a.type = NodeAnimator.Type.Send;
                    result.add(a);
                    /// for edge
                    String n0 = e.sourceId;
                    String n1 = e.destId;
                    if (graph.getNode(n1) == null) {
                        return null;
                    }
                    EdgeAnimator ea = new EdgeAnimator();
                    ea.n0 = n0;
                    ea.n1 = n1;
                    ea.packetID = e.packetId;
                    ea.id = e.packetId + "-" + e.getTime();
                    if (e.timeReceive.isEmpty() || e.timeReceive == null) {
                        ea.speed = 0.0023;
                    } else {
                        ea.speed = getBasedSpeed(e.getTime(), e.getTimeReceive());
                    }
                    ea.timeStart = -1;
                    ea.type = EdgeAnimator.Type.SEND;
                    result.add(ea);
                }
                break;
            case "forward":
                if (e.destId.equals("-1")) {
                    // broadcast
                    return null;
                } 
                else 
                {   // simple forward
                    /// for node
                    a = new NodeAnimator();
                    a.id = e.nodeId + e.getTime();
                    a.NodeID = e.sourceId;
                    a.type = NodeAnimator.Type.Forward;
                    result.add(a);
                    /// for edge
                    String n0 = e.sourceId;
                    String n1 = e.destId;
                    if (graph.getNode(n1) == null) {
                        return null;
                    }
                    EdgeAnimator ea = new EdgeAnimator();
                    ea.n0 = n0;
                    ea.n1 = n1;
                    ea.packetID = e.packetId;
                    ea.id = e.packetId + "-" + n0 + "-" + n1;
                    if (e.timeReceive.isEmpty() || e.timeReceive == null) {
                        ea.speed = 0.0023;
                    } else {
                        ea.speed = getSpeed(e.getTime(), e.getTimeReceive());
                    }

                    ea.timeStart = -1;
                    ea.type = EdgeAnimator.Type.FORWARD;
                    result.add(ea);
                }
                break;
            case "receive":
                 /// for node
//                    a = new NodeAnimator();
//                    a.id = e.nodeId + e.getTime();
//                    a.NodeID = e.sourceId;
//                    a.type = NodeAnimator.Type.Receive;
//                    result.add(a);
                break;
            default:
                break;
        }
        
        return result;
    }
}
